home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / faq-s.zip / PIBASYN2.MOD < prev    next >
Text File  |  1988-04-11  |  36KB  |  535 lines

  1. (*----------------------------------------------------------------------*)
  2. (*          Async_Send --- Send character over communications port      *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Async_Send( C : Char );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Async_Send                                           *)
  10. (*                                                                      *)
  11. (*     Purpose:    Sends character out over communications port         *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Async_Send( C : Char );                                       *)
  16. (*                                                                      *)
  17. (*           C --- Character to send                                    *)
  18. (*                                                                      *)
  19. (*     Calls:  None                                                     *)
  20. (*                                                                      *)
  21. (*----------------------------------------------------------------------*)
  22.  
  23. BEGIN   (* Async_Send *)
  24.  
  25. INLINE(
  26.   $8B/$1E/>ASYNC_OBUFFER_HEAD/         {         MOV     BX,[>Async_OBuffer_Head]   ;Get output queue head pointer}
  27.   $C4/$3E/>ASYNC_OBUFFER_PTR/          {         LES     DI,[>Async_OBuffer_Ptr]    ;Pick up output buffer address}
  28.   $01/$DF/                             {         ADD     DI,BX                      ;Position to current character}
  29.                                        {;}
  30.   $89/$DA/                             {         MOV     DX,BX                      ;Save previous head pointer}
  31.   $43/                                 {         INC     BX                         ;Increment head pointer}
  32.   $3B/$1E/>ASYNC_OBUFFER_SIZE/         {         CMP     BX,[>Async_OBuffer_Size]   ;See if past end of buffer}
  33.   $7E/$02/                             {         JLE     Send1                      ;Skip if not}
  34.   $31/$DB/                             {         XOR     BX,BX                      ;Wrap to start of buffer}
  35.                                        {;}
  36.   $3B/$1E/>ASYNC_OBUFFER_TAIL/         {Send1:   CMP     BX,[>Async_OBuffer_Tail]   ;See if head collided with tail}
  37.   $75/$1C/                             {         JNE     Send4                      ;No -- buffer didn't fill up}
  38.                                        {;}
  39.   $8B/$0E/>ASYNC_OUTPUT_DELAY/         {         MOV     CX,[>Async_Output_Delay]   ;Run delay loop and see if buffer drains}
  40.                                        {;}
  41.   $51/                                 {Send2:   PUSH    CX                         ;Save milleseconds to go}
  42.   $8B/$0E/>ASYNC_ONEMSDELAY/           {         MOV     CX,[>Async_OneMSDelay]     ;Get delay loop value for 1 ms}
  43.                                        {;}
  44.   $E2/$FE/                             {Send3:   LOOP    Send3                      ;Tight loop for 1 ms delay}
  45.                                        {;}
  46.   $59/                                 {         POP     CX                         ;Get back millesecond count}
  47.                                        {;}
  48.   $3B/$1E/>ASYNC_OBUFFER_TAIL/         {         CMP     BX,[>Async_OBuffer_Tail]   ;See if buffer drained yet}
  49.   $75/$0A/                             {         JNE     Send4                      ;Yes -- OK, stop delay loop.}
  50.                                        {;}
  51.   $E2/$F0/                             {         LOOP    Send2                      ;Decrement millesecond count and loop}
  52.                                        {;}
  53.   $C6/$06/>ASYNC_OBUFFER_OVERFLOW/$01/ {         MOV     BYTE [>Async_OBuffer_Overflow],1 ;Indicate output buffer overflow}
  54.   $E9/$1A/$00/                         {         JMP     Send5                      ;Skip updating head pointers}
  55.                                        {;}
  56.   $89/$1E/>ASYNC_OBUFFER_HEAD/         {Send4:   MOV     [>Async_OBuffer_Head],BX   ;Save updated head pointer}
  57.   $8A/$46/<C/                          {         MOV     AL,[BP+<C]                 ;Pick up character to send}
  58.   $26/$88/$05/                         {     ES: MOV     [DI],AL                    ;Place character in output buffer}
  59.                                        {;}
  60.   $A1/>ASYNC_OBUFFER_USED/             {         MOV     AX,[>Async_OBuffer_Used]   ;Get buffer use count}
  61.   $40/                                 {         INC     AX                         ;Increment buffer use count}
  62.   $A3/>ASYNC_OBUFFER_USED/             {         MOV     [>Async_OBuffer_Used],AX   ;Save new count}
  63.   $3B/$06/>ASYNC_MAXOBUFFERUSED/       {         CMP     AX,[>Async_MaxOBufferUsed] ;See if larger than ever before}
  64.   $7E/$03/                             {         JLE     Send5                      ;Skip if not}
  65.   $A3/>ASYNC_MAXOBUFFERUSED/           {         MOV     [>Async_MaxOBufferUsed],AX ;Save new maximum usage}
  66.                                        {;}
  67.   $8B/$16/>ASYNC_UART_IER/             {Send5:   MOV     DX,[>Async_Uart_IER]       ;Get interrupt enable register}
  68.   $EC/                                 {         IN      AL,DX                      ;Check contents of IER}
  69.   $A8/$02/                             {         TEST    AL,2                       ;See if write interrupt enabled}
  70.   $75/$03/                             {         JNZ     Send6                      ;Skip if so}
  71.   $0C/$02/                             {         OR      AL,2                       ;Else enable write interrupts ...}
  72.   $EE);                                {         OUT     DX,AL                      ;... by rewriting IER contents}
  73.                                        {;}
  74.                                        {Send6:}
  75.  
  76. END    (* Async_Send *);
  77.  
  78. (*----------------------------------------------------------------------*)
  79. (*          Async_Receive --- Return character from buffer              *)
  80. (*----------------------------------------------------------------------*)
  81.  
  82. FUNCTION Async_Receive( VAR C : Char ) : BOOLEAN;
  83.  
  84. (*----------------------------------------------------------------------*)
  85. (*                                                                      *)
  86. (*     Function:   Async_Receive                                        *)
  87. (*                                                                      *)
  88. (*     Purpose:    Retrieve character (if any) from buffer              *)
  89. (*                                                                      *)
  90. (*     Calling Sequence:                                                *)
  91. (*                                                                      *)
  92. (*        Flag := Async_Receive( VAR C: Char ) : BOOLEAN;               *)
  93. (*                                                                      *)
  94. (*           C --- character (if any) retrieved from buffer;            *)
  95. (*                 set to CHR(0) if no character available.             *)
  96. (*                                                                      *)
  97. (*           Flag returned TRUE if character retrieved from buffer,     *)
  98. (*           Flag returned FALSE if no character retrieved.             *)
  99. (*                                                                      *)
  100. (*     Calls:  None                                                     *)
  101. (*                                                                      *)
  102. (*----------------------------------------------------------------------*)
  103.  
  104. BEGIN   (* Async_Receive *)
  105.  
  106. INLINE(
  107.                                   {;}
  108.                                   {;  Check if any characters in input comm buffer}
  109.                                   {;}
  110.   $A1/>ASYNC_BUFFER_TAIL/         {         MOV   AX,[>Async_Buffer_Tail]}
  111.   $3B/$06/>ASYNC_BUFFER_HEAD/     {         CMP   AX,[>Async_Buffer_Head]}
  112.   $75/$0B/                        {         JNE   Rec1}
  113.                                   {;}
  114.                                   {;  Buffer is empty -- return NUL character}
  115.                                   {;}
  116.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                   ;Get character address}
  117.   $31/$C0/                        {         XOR   AX,AX                        ;Clear out unused bits}
  118.   $26/$88/$05/                    {     ES: MOV   [DI],AL                      ;NUL character}
  119.   $E9/$69/$00/                    {         JMP   Return}
  120.                                   {;}
  121.                                   {;  Buffer not empty -- pick up next character.}
  122.                                   {;}
  123.   $C4/$3E/>ASYNC_BUFFER_PTR/      {Rec1:    LES   DI,[>Async_Buffer_Ptr]       ;Pick up buffer address}
  124.   $01/$C7/                        {         ADD   DI,AX                        ;Add character offset}
  125.   $26/$8A/$1D/                    {     ES: MOV   BL,[DI]                      ;Get character from buffer}
  126.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                   ;Get result address}
  127.   $26/$88/$1D/                    {     ES: MOV   [DI],BL                      ;Store character from buffer}
  128.   $40/                            {         INC   AX                           ;Increment tail pointer}
  129.   $3B/$06/>ASYNC_BUFFER_SIZE/     {         CMP   AX,[>Async_Buffer_Size]      ;Past end of buffer?}
  130.   $7E/$02/                        {         JLE   Rec2                         ;No -- skip wrapping}
  131.   $31/$C0/                        {         XOR   AX,AX                        ;Yes -- point to start of buffer}
  132.   $A3/>ASYNC_BUFFER_TAIL/         {Rec2:    MOV   [>Async_Buffer_Tail],AX      ;Update tail pointer}
  133.   $A1/>ASYNC_BUFFER_USED/         {         MOV   AX,[>Async_Buffer_Used]      ;Pick up amount of buffer used}
  134.   $48/                            {         DEC   AX                           ;Update buffer use count}
  135.   $A3/>ASYNC_BUFFER_USED/         {         MOV   [>Async_Buffer_Used],AX      ;}
  136.                                   {;}
  137.                                   {; Check how empty the receive buffer is.}
  138.                                   {; We may have previously sent XOFF, or dropped RTS, to}
  139.                                   {; stop sender from sending.  If so, and the buffer is}
  140.                                   {; now empty enough, we should re-enable the sender.}
  141.                                   {;}
  142.   $F6/$06/>ASYNC_SENDER_ON/$01/   {         TEST  BYTE [<Async_Sender_On],1    ;See if sender enabled}
  143.   $75/$3D/                        {         JNZ   Rec6                         ;Skip buffer tests if so}
  144.                                   {;}
  145.   $3B/$06/>ASYNC_BUFFER_LOW/      {         CMP   AX,[>Async_Buffer_Low]       ;Check if low enough}
  146.   $7F/$37/                        {         JG    Rec6                         ;Still too full, skip}
  147.                                   {;}
  148.                                   {; Buffer is reasonably empty, send XON to get things rolling again}
  149.                                   {; if XOFF previously sent.}
  150.                                   {;}
  151.   $F6/$06/>ASYNC_XOFF_SENT/$01/   {         TEST  BYTE [<Async_XOff_Sent],1    ;Check if Xoff sent}
  152.   $74/$0D/                        {         JZ    Rec3                         ;No -- skip.}
  153.                                   {;}
  154.   $B8/>XON/                       {         MOV   AX,>XON                      ;Else push XON onto stack}
  155.   $50/                            {         PUSH  AX}
  156.   $FF/$1E/>ASYNC_SEND_ADDR/       {         CALL  FAR [>Async_Send_Addr]       ;Call output routine}
  157.                                   {;}
  158.   $C6/$06/>ASYNC_XOFF_SENT/$00/   {         MOV   BYTE [>Async_XOff_Sent],0    ;Clear Xoff flag}
  159.                                   {;}
  160.                                   {; If RTS dropped because buffer was too full, enable RTS.}
  161.                                   {;}
  162.   $F6/$06/>ASYNC_DO_CTS/$01/      {Rec3:    TEST    BYTE [<Async_Do_Cts],1     ;Check if CTS/RTS checking}
  163.   $74/$08/                        {         JZ      Rec4                       ;No -- skip}
  164.                                   {;}
  165.   $8B/$16/>ASYNC_UART_MCR/        {         MOV     DX,[>Async_Uart_MCR]       ;Get modem control register}
  166.   $EC/                            {         IN      AL,DX}
  167.   $0C/<ASYNC_RTS/                 {         OR      AL,<Async_RTS              ;Enable RTS}
  168.   $EE/                            {         OUT     DX,AL}
  169.                                   {;}
  170.                                   {; If DTR dropped because buffer was too full, enable DTR.}
  171.                                   {;}
  172.   $F6/$06/>ASYNC_DO_DSR/$01/      {Rec4:    TEST    BYTE [<Async_Do_Dsr],1     ;Check if DSR/DTR checking}
  173.   $74/$08/                        {         JZ      Rec5                       ;No -- skip}
  174.                                   {;}
  175.   $8B/$16/>ASYNC_UART_MCR/        {         MOV     DX,[>Async_Uart_MCR]       ;Get modem control register}
  176.   $EC/                            {         IN      AL,DX}
  177.   $0C/<ASYNC_DTR/                 {         OR      AL,<Async_DTR              ;Enable DTR}
  178.   $EE/                            {         OUT     DX,AL}
  179.                                   {;}
  180.   $C6/$06/>ASYNC_SENDER_ON/$01/   {Rec5:    MOV     BYTE [>Async_Sender_On],1  ;Indicate sender enabled}
  181.                                   {;}
  182.                                   {;  Indicate character found}
  183.                                   {;}
  184.   $B8/$01/$00/                    {Rec6:    MOV    AX,1}
  185.                                   {;}
  186.   $80/$26/>ASYNC_LINE_STATUS/$FD/ {Return:  AND    Byte [>Async_Line_Status],$FD ;Remove overflow flag}
  187.   $09/$C0/                        {         OR     AX,AX                       ;Set zero flag to indicate return status}
  188.   $89/$EC/                        {         MOV    SP,BP}
  189.   $5D/                            {         POP    BP}
  190.   $CA/$04/$00);                   {         RETF   4}
  191.  
  192. END   (* Async_Receive *);
  193.  
  194. (*----------------------------------------------------------------------*)
  195. (*   Async_Receive_With_TimeOut --- Return char. from buffer with delay *)
  196. (*----------------------------------------------------------------------*)
  197.  
  198. PROCEDURE Async_Receive_With_Timeout( Secs : INTEGER; VAR C : INTEGER );
  199.  
  200. (*----------------------------------------------------------------------*)
  201. (*                                                                      *)
  202. (*     Procedure:  Async_Receive_With_Timeout                           *)
  203. (*                                                                      *)
  204. (*     Purpose:    Retrieve character as integer from buffer,           *)
  205. (*                 or return TimeOut if specified delay period          *)
  206. (*                 expires.                                             *)
  207. (*                                                                      *)
  208. (*     Calling Sequence:                                                *)
  209. (*                                                                      *)
  210. (*        Async_Receive_With_Timeout( Secs: INTEGER; VAR C: INTEGER );  *)
  211. (*                                                                      *)
  212. (*           Secs ---  Timeout period in seconds                        *)
  213. (*                     NOTE:  Cannot be longer than 32 seconds!         *)
  214. (*           C     --- ORD(character) (if any) retrieved from buffer;   *)
  215. (*                     set to TimeOut if no character found before      *)
  216. (*                     delay period expires.                            *)
  217. (*                                                                      *)
  218. (*     Calls:  Async_Receive                                            *)
  219. (*                                                                      *)
  220. (*     WATCH OUT!  THIS ROUTINE RETURNS AN INTEGER, NOT A CHARACTER!!!  *)
  221. (*                                                                      *)
  222. (*----------------------------------------------------------------------*)
  223.  
  224. BEGIN (* Async_Receive_With_Timeout *)
  225.  
  226. INLINE(
  227.                                   {;}
  228.                                   {;  Check if a character in input comm buffer}
  229.                                   {;}
  230.   $A1/>ASYNC_BUFFER_TAIL/         {         MOV   AX,[>Async_Buffer_Tail]}
  231.   $3B/$06/>ASYNC_BUFFER_HEAD/     {         CMP   AX,[>Async_Buffer_Head]}
  232.   $75/$29/                        {         JNE   Rec1}
  233.                                   {;}
  234.                                   {;  Buffer empty -- begin wait loop.}
  235.                                   {;}
  236.   $8B/$46/<SECS/                  {         MOV   AX,[BP+<Secs]                 ;Get seconds to wait}
  237.   $B9/$0A/$00/                    {         MOV   CX,10                         ;Shift count = 2 ** 10 = 1024}
  238.   $D3/$E0/                        {         SHL   AX,CL                         ;Seconds * 1024 = milleseconds}
  239.   $89/$C1/                        {         MOV   CX,AX                         ;Move to looping register}
  240.                                   {;}
  241.                                   {;  Delay for 1 ms.}
  242.                                   {;}
  243.   $51/                            {Delay:   PUSH  CX                            ;Save milleseconds to go}
  244.   $8B/$0E/>ASYNC_ONEMSDELAY/      {         MOV   CX,[>Async_OneMSDelay]        ;Get delay loop value for 1 ms}
  245.   $E2/$FE/                        {Delay1:  LOOP  Delay1                        ;Tight loop for 1 ms delay}
  246.                                   {;}
  247.                                   {;  Check if any character yet.}
  248.                                   {;}
  249.   $59/                            {         POP   CX                            ;Get back millesecond count}
  250.                                   {;}
  251.   $A1/>ASYNC_BUFFER_TAIL/         {         MOV   AX,[>Async_Buffer_Tail]}
  252.   $3B/$06/>ASYNC_BUFFER_HEAD/     {         CMP   AX,[>Async_Buffer_Head]}
  253.   $75/$0E/                        {         JNE   Rec1}
  254.                                   {;}
  255.                                   {;  Buffer still empty -- decrement elapsed time}
  256.                                   {;}
  257.   $E2/$ED/                        {         LOOP  Delay                         ;Decrement millesecond count and loop}
  258.                                   {;}
  259.                                   {;  Dropped through -- no character arrived in specified interval.}
  260.                                   {;  Return TimeOut as result.}
  261.                                   {;}
  262.   $BB/>TIMEOUT/                   {         MOV   BX,>TimeOut                   ;Pick up timeout value}
  263.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                    ;Get result character address}
  264.   $26/$89/$1D/                    {    ES:  MOV   [DI],BX                       ;Store timeout value}
  265.   $E9/$68/$00/                    {         JMP   Return                        ;Return to caller}
  266.                                   {;}
  267.                                   {;  Buffer not empty -- pick up next character.}
  268.                                   {;}
  269.   $C4/$3E/>ASYNC_BUFFER_PTR/      {Rec1:    LES   DI,[>Async_Buffer_Ptr]        ;Pick up buffer address}
  270.   $01/$C7/                        {         ADD   DI,AX                         ;Add character offset}
  271.   $26/$8A/$1D/                    {     ES: MOV   BL,[DI]                       ;Get character from buffer}
  272.                                   {;}
  273.   $30/$FF/                        {         XOR   BH,BH                         ;Clear high-order bits}
  274.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                    ;Get result address}
  275.   $26/$89/$1D/                    {     ES: MOV   [DI],BX                       ;Store character from buffer}
  276.                                   {;}
  277.   $40/                            {         INC   AX                            ;Increment tail pointer}
  278.   $3B/$06/>ASYNC_BUFFER_SIZE/     {         CMP   AX,[>Async_Buffer_Size]       ;Past end of buffer?}
  279.   $7E/$02/                        {         JLE   Rec2                          ;No -- skip wrapping}
  280.   $31/$C0/                        {         XOR   AX,AX                         ;Yes -- point to start of buffer}
  281.   $A3/>ASYNC_BUFFER_TAIL/         {Rec2:    MOV   [>Async_Buffer_Tail],AX       ;Update tail pointer}
  282.   $A1/>ASYNC_BUFFER_USED/         {         MOV   AX,[>Async_Buffer_Used]       ;Pick up amount of buffer used}
  283.   $48/                            {         DEC   AX                            ;Update buffer use count}
  284.   $A3/>ASYNC_BUFFER_USED/         {         MOV   [>Async_Buffer_Used],AX       ;}
  285.                                   {;}
  286.                                   {; Check how empty the receive buffer is.}
  287.                                   {; We may have previously sent XOFF, or dropped RTS, to}
  288.                                   {; stop sender from sending.  If so, and the buffer is}
  289.                                   {; now empty enough, we should re-enable the sender.}
  290.                                   {;}
  291.   $F6/$06/>ASYNC_SENDER_ON/$01/   {         TEST  BYTE [<Async_Sender_On],1     ;See if sender enabled}
  292.   $75/$3D/                        {         JNZ   Return                        ;Skip buffer tests if so}
  293.                                   {;}
  294.   $3B/$06/>ASYNC_BUFFER_LOW/      {         CMP   AX,[>Async_Buffer_Low]        ;Check if low enough}
  295.   $7F/$37/                        {         JG    Return                        ;Still too full, skip}
  296.                                   {;}
  297.                                   {; Buffer is reasonably empty, send XON to get things rolling again}
  298.                                   {; if XOFF previously sent.}
  299.                                   {;}
  300.   $F6/$06/>ASYNC_XOFF_SENT/$01/   {         TEST  BYTE [<Async_XOff_Sent],1     ;Check if Xoff sent}
  301.   $74/$0D/                        {         JZ    Rec3                          ;No -- skip.}
  302.                                   {;}
  303.   $B8/>XON/                       {         MOV   AX,>XON                       ;Else push XON onto stack}
  304.   $50/                            {         PUSH  AX}
  305.   $FF/$1E/>ASYNC_SEND_ADDR/       {         CALL  FAR [>Async_Send_Addr]        ;Call output routine}
  306.                                   {;}
  307.   $C6/$06/>ASYNC_XOFF_SENT/$00/   {         MOV   BYTE [>Async_XOff_Sent],0     ;Clear Xoff flag}
  308.                                   {;}
  309.                                   {; If RTS dropped because buffer was too full, enable RTS.}
  310.                                   {;}
  311.   $F6/$06/>ASYNC_DO_CTS/$01/      {Rec3:    TEST    BYTE [<Async_Do_Cts],1      ;Check if CTS/RTS checking}
  312.   $74/$08/                        {         JZ      Rec4                        ;No -- skip}
  313.                                   {;}
  314.   $8B/$16/>ASYNC_UART_MCR/        {         MOV     DX,[>Async_Uart_MCR]        ;Get modem control register}
  315.   $EC/                            {         IN      AL,DX}
  316.   $0C/<ASYNC_RTS/                 {         OR      AL,<Async_RTS               ;Enable RTS}
  317.   $EE/                            {         OUT     DX,AL}
  318.                                   {;}
  319.                                   {; If DTR dropped because buffer was too full, enable DTR.}
  320.                                   {;}
  321.   $F6/$06/>ASYNC_DO_DSR/$01/      {Rec4:    TEST    BYTE [<Async_Do_Dsr],1      ;Check if DSR/DTR checking}
  322.   $74/$08/                        {         JZ      Rec5                        ;No -- skip}
  323.                                   {;}
  324.   $8B/$16/>ASYNC_UART_MCR/        {         MOV     DX,[>Async_Uart_MCR]        ;Get modem control register}
  325.   $EC/                            {         IN      AL,DX}
  326.   $0C/<ASYNC_DTR/                 {         OR      AL,<Async_DTR               ;Enable DTR}
  327.   $EE/                            {         OUT     DX,AL}
  328.                                   {;}
  329.   $C6/$06/>ASYNC_SENDER_ON/$01/   {Rec5:    MOV     BYTE [>Async_Sender_On],1   ;Indicate sender enabled}
  330.   $80/$26/>ASYNC_LINE_STATUS/$FD);{Return:  AND     Byte [>Async_Line_Status],$FD ;Remove overflow flag}
  331.  
  332. END   (* Async_Receive_With_Timeout *);
  333.  
  334. (*----------------------------------------------------------------------*)
  335. (*        Async_Stuff --- Stuff character into receive buffer           *)
  336. (*----------------------------------------------------------------------*)
  337.  
  338. PROCEDURE Async_Stuff( Ch: CHAR );
  339.  
  340. (*----------------------------------------------------------------------*)
  341. (*                                                                      *)
  342. (*     Procedure:  Async_Stuff                                          *)
  343. (*                                                                      *)
  344. (*     Purpose:    Stuffs a character into receive buffer               *)
  345. (*                                                                      *)
  346. (*     Calling Sequence:                                                *)
  347. (*                                                                      *)
  348. (*        Async_Stuff( Ch : Char );                                     *)
  349. (*                                                                      *)
  350. (*           Ch --- Character to stuff                                  *)
  351. (*                                                                      *)
  352. (*     Calls:  None                                                     *)
  353. (*                                                                      *)
  354. (*----------------------------------------------------------------------*)
  355.  
  356. VAR
  357.    New_Head : INTEGER;
  358.  
  359. BEGIN (* Async_Stuff *)
  360.  
  361.    Async_Buffer_Ptr^[Async_Buffer_Head] := Ch;
  362.    New_Head                             := SUCC( Async_Buffer_Head ) MOD
  363.                                            SUCC( Async_Buffer_Size );
  364.  
  365.    IF ( New_Head = Async_Buffer_Tail ) THEN
  366.       Async_Buffer_Overflow := TRUE
  367.    ELSE
  368.       BEGIN
  369.          Async_Buffer_Head := New_Head;
  370.          INC( Async_Buffer_Used );
  371.          IF ( Async_Buffer_Used > Async_MaxBufferUsed ) THEN
  372.             Async_MaxBufferUsed := Async_Buffer_Used;
  373.       END;
  374.  
  375. END   (* Async_Stuff *);
  376.  
  377. (*----------------------------------------------------------------------*)
  378. (*          Async_Wait_For_Quiet --- Wait for port to quiesce           *)
  379. (*----------------------------------------------------------------------*)
  380.  
  381. FUNCTION Async_Wait_For_Quiet( Max_Wait : LONGINT;
  382.                                Wait_Time: LONGINT  ) : BOOLEAN;
  383.  
  384. (*----------------------------------------------------------------------*)
  385. (*                                                                      *)
  386. (*     Procedure:  Async_Wait_For_Quiet                                 *)
  387. (*                                                                      *)
  388. (*     Purpose:    Waits for serial port input to quiesce.              *)
  389. (*                                                                      *)
  390. (*     Calling Sequence:                                                *)
  391. (*                                                                      *)
  392. (*        Async_Wait_For_Quiet( Max_Wait  : LONGINT;                    *)
  393. (*                              Wait_Time : LONGINT  ) : BOOLEAN;       *)
  394. (*                                                                      *)
  395. (*           Max_Wait   --- Total time in 1/100 seconds to wait for     *)
  396. (*                          quiet.                                      *)
  397. (*           Wait_Time  --- Length of time without receiving character  *)
  398. (*                          which is assumed to mean port is quiet.     *)
  399. (*                                                                      *)
  400. (*     Calls:  None                                                     *)
  401. (*                                                                      *)
  402. (*----------------------------------------------------------------------*)
  403.  
  404. VAR
  405.    T1   : LONGINT;
  406.    W1   : LONGINT;
  407.    Head : INTEGER;
  408.  
  409. BEGIN (* Async_Wait_For_Quiet *)
  410.                                    (* Get current time of day *)
  411.    T1 := TimeOfDayH;
  412.                                    (* Outer loop runs over maximum time *)
  413.                                    (* to wait for quiet spell to appear *)
  414.    REPEAT
  415.                                    (* Get time defining "quiet" for  *)
  416.                                    (* our purposes in 1/100th secs.  *)
  417.       W1 := Wait_Time;
  418.                                    (* Delay 1/100th second and then  *)
  419.                                    (* see if receive buffer head     *)
  420.                                    (* has changed or not.  If head   *)
  421.                                    (* changed, drop through to start *)
  422.                                    (* check over again.              *)
  423.       REPEAT
  424.          DELAY( 10 );
  425.          DEC  ( W1 );
  426.       UNTIL  ( ( W1 = 0 ) OR ( Head <> Async_Buffer_Head ) );
  427.  
  428.                                    (* Check if maximum wait time is  *)
  429.                                    (* exhausted -- quit if so.  Else *)
  430.                                    (* if buffer head didn't change,  *)
  431.                                    (* then port is quiet, so quit.   *)
  432.                                    (* Else keep on going.            *)
  433.  
  434.    UNTIL ( ( TimeDiffH( T1 , TimeOfDay ) > Max_Wait ) OR
  435.            ( Head = Async_Buffer_Head ) );
  436.  
  437.                                    (* If we dropped through with   *)
  438.                                    (* the buffer head not changed, *)
  439.                                    (* this means that the port     *)
  440.                                    (* is quiet.                    *)
  441.  
  442.    Async_Wait_For_Quiet := ( Head = Async_Buffer_Head );
  443.  
  444. END   (* Async_Wait_For_Quiet *);
  445.  
  446. (*----------------------------------------------------------------------*)
  447. (*      Async_Send_Now --- Send character over communications port      *)
  448. (*----------------------------------------------------------------------*)
  449.  
  450. PROCEDURE Async_Send_Now( C : Char );
  451.  
  452. (*----------------------------------------------------------------------*)
  453. (*                                                                      *)
  454. (*     Procedure:  Async_Send_Now                                       *)
  455. (*                                                                      *)
  456. (*     Purpose:    Sends character out over communications port         *)
  457. (*                                                                      *)
  458. (*     Calling Sequence:                                                *)
  459. (*                                                                      *)
  460. (*        Async_Send_Now( C : Char );                                   *)
  461. (*                                                                      *)
  462. (*           C --- Character to send                                    *)
  463. (*                                                                      *)
  464. (*     Calls:  None                                                     *)
  465. (*                                                                      *)
  466. (*     Remarks:                                                         *)
  467. (*                                                                      *)
  468. (*        This routine differs from Async_Send in that Async_Send_Now   *)
  469. (*        transmits the given character as soon as possible, ignoring   *)
  470. (*        the contents of the current output buffer.  This behavior     *)
  471. (*        is useful if a character MUST be sent ASAP -- for example,    *)
  472. (*        an XOFF.                                                      *)
  473. (*                                                                      *)
  474. (*----------------------------------------------------------------------*)
  475.  
  476. BEGIN   (* Async_Send_Now *)
  477.  
  478. INLINE(
  479.                              {;}
  480.                              {;        Activate sending of characters}
  481.                              {;}
  482.   $8B/$16/>ASYNC_UART_MCR/   {          MOV    DX,[>Async_Uart_MCR]       ;Get modem control register}
  483.   $EC/                       {          IN     AL,DX}
  484.   $0C/$0B/                   {          OR     AL,$0B                     ;Turn on OUT2, DTR, and RTS}
  485.   $EE/                       {          OUT    DX,AL}
  486.                              {;}
  487.   $8B/$16/>ASYNC_UART_MSR/   {          MOV    DX,[>Async_Uart_MSR]       ;Get modem status register address}
  488.                              {;}
  489.                              {;         Wait for DSR using Busy Wait}
  490.                              {;}
  491.   $F6/$06/>ASYNC_DO_DSR/$01/ {          TEST   BYTE [>Async_Do_DSR],1     ;See if doing DSR check}
  492.   $74/$0D/                   {          JZ     SendNow2                   ;No -- skip check}
  493.                              {;}
  494.   $B9/$FF/$FF/               {          MOV    CX,$FFFF                   ;Large count for busy wait}
  495.                              {;}
  496.   $EC/                       {SendNow1: IN     AL,DX                      ;Read modem status register}
  497.   $A8/<ASYNC_DSR/            {          TEST   AL,<Async_DSR              ;Check for DSR}
  498.   $75/$05/                   {          JNZ    SendNow2}
  499.   $E2/$F9/                   {          LOOP   SendNow1}
  500.   $E9/$2E/$00/               {          JMP    Exit                       ;Quit if we fall through}
  501.                              {;}
  502.                              {;         Wait for CTS using Busy Wait}
  503.                              {;}
  504.   $F6/$06/>ASYNC_DO_CTS/$01/ {SendNow2: TEST   BYTE [>Async_Do_CTS],1     ;See if doing CTS check}
  505.   $74/$0D/                   {          JZ     SendNow4                   ;No -- skip check}
  506.                              {;}
  507.   $B9/$FF/$FF/               {          MOV    CX,$FFFF                   ;Restore count}
  508.                              {;}
  509.   $EC/                       {SendNow3: IN     AL,DX                      ;Read modem status register}
  510.   $A8/<ASYNC_CTS/            {          TEST   AL,<Async_CTS              ;Check for CTS}
  511.   $75/$05/                   {          JNZ    SendNow4}
  512.   $E2/$F9/                   {          LOOP   SendNow3}
  513.   $E9/$1A/$00/               {          JMP    Exit                       ;Quit if we fall through}
  514.                              {;}
  515.                              {;         Wait for Transmit Hold Register Empty (THRE)}
  516.                              {;}
  517.   $B9/$FF/$FF/               {SendNow4: MOV    CX,$FFFF                   ;Restore count}
  518.   $8B/$16/>ASYNC_UART_LSR/   {          MOV    DX,[>Async_Uart_LSR]       ;Get line status register address}
  519.                              {;}
  520.   $EC/                       {SendNow5: IN     AL,DX                      ;Read line status register}
  521.   $A8/<ASYNC_THRE/           {          TEST   AL,<Async_THRE             ;Check for THRE empty}
  522.   $75/$05/                   {          JNZ    SendNow6}
  523.   $E2/$F9/                   {          LOOP   SendNow5}
  524.   $E9/$09/$00/               {          JMP    Exit                       ;Quit if we fall through}
  525.                              {;}
  526.                              {;         Send the character when port clear}
  527.                              {;}
  528.   $8A/$86/>C/                {SendNow6: MOV    AL,[BP+>C]                 ;Get character to transmit}
  529.   $8B/$16/>ASYNC_UART_THR/   {          MOV    DX,[>Async_Uart_THR]       ;Get transmit hold register}
  530.   $EE);                      {          OUT    DX,AL                      ;Send the character}
  531.                              {;}
  532.                              {Exit:}
  533.  
  534. END    (* Async_Send_Now *);
  535.